package com.koron.rating.change;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.google.common.collect.Lists;
import com.koron.bean.base.Constants;
import com.koron.bean.base.Response;
import com.koron.bean.system.org.OrgBean;
import com.koron.bean.system.role.AppOrgJurisdictionBean;
import com.koron.bean.system.role.UserOwnJurisdictionBean;
import com.koron.bean.system.staff.vo.EamUser;
import com.koron.common.core.config.ThreadLocalContext;
import com.koron.common.core.util.CodeTools;
import com.koron.common.core.util.CommonUtils;
import com.koron.common.core.util.OrgCacheUtils;
import com.koron.rating.change.bean.*;
import com.koron.rating.change.mapper.UnitChangeBeanMapper;
import com.koron.rating.change.mapper.UnitChangeDetBeanMapper;
import com.koron.rating.change.mapper.UnitEquipmentDetBeanMapper;
import com.koron.rating.change.mapper.UnitOldBeanMapper;
import com.koron.rating.classify.bean.RatingUnitSortDto;
import com.koron.rating.classify.bean.Select;
import com.koron.rating.classify.services.SystemFeignService;
import com.koron.rating.enums.RatingChangeEnum;
import com.koron.rating.enums.UnitSortTypeEnum;
import com.koron.rating.enums.UnitTypeEnum;
import org.apache.commons.lang3.StringUtils;
import org.koron.ebs.mybatis.SessionFactory;
import org.koron.ebs.mybatis.TaskAnnotation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

import static com.koron.rating.enums.UnitTypeEnum.*;

@Service
public class UnitChangeService {

    private EamUser getEamUser() {
        return ThreadLocalContext.get();
    }

    @Autowired
    private OrgCacheUtils orgCacheUtils;

    @Autowired
    private SystemFeignService systemFeignService;

    @TaskAnnotation("insert")
    public Response insert(SessionFactory factory, UnitChangeDetBean ratingunit) {

        UnitChangeDetBeanMapper mapper = factory.getMapper(UnitChangeDetBeanMapper.class);
        UnitEquipmentDetBeanMapper equipmentdetmapper = factory.getMapper(UnitEquipmentDetBeanMapper.class);
        if (StringUtils.isEmpty(ratingunit.getParentId())) {
            // 没有父级，说明是根节点
            ratingunit.setParentId(Constants.DEVICE_TREE_ROOT_CODE);
        }
        ratingunit.setPrimaryId(CodeTools.getCode32());
        ratingunit.setId(CodeTools.getCode32());
        UnitChangeDetBean parent = mapper.selectByChangeIdAndId(ratingunit.getChangeId(), ratingunit.getParentId());
        // 如果根节点不存在，则设置默认根节点
        if (Objects.isNull(parent)) {
            ratingunit.setParentName("0");
            ratingunit.setLevel(1);
            ratingunit.setFullPathCode(ratingunit.getId());
            ratingunit.setFullPathName(ratingunit.getName());
        } else {
            ratingunit.setParentName(parent.getName());
            // 父级level+1
            ratingunit.setLevel(parent.getLevel() + 1);
            ratingunit.setFullPathCode(parent.getFullPathCode() + "/" + ratingunit.getId());
            ratingunit.setFullPathName(parent.getFullPathName() + "/" + ratingunit.getName());
            //单元、设备、部件 级带上 父级单位id
            if (Lists.newArrayList("4", "5", "6").contains(ratingunit.getUnitType())) {
                ratingunit.setDeptId(parent.getDeptId());
                ratingunit.setDeptName(parent.getDeptName());
            }
        }
        if (ratingunit.getUnitType().compareTo(parent.getUnitType()) == -1) {
            return Response.fail("单元类型选择错误");
        }
        // 获取该层级的最大编码
        Integer maxLevelCode = mapper.getMaxLevelCodeByLevelAndChangeId(ratingunit.getLevel(), ratingunit.getChangeId());
        maxLevelCode = maxLevelCode == null ? 1 : maxLevelCode + 1;
        ratingunit.setLevelCode(maxLevelCode);
        ratingunit.setSort(maxLevelCode);

        if ("0".equals(ratingunit.getParentId())) {
            ratingunit.setLevelPath(maxLevelCode + "");
        } else {
            String levelPath = mapper.queryLevelPathByIdAndChangeId(ratingunit.getParentId(), ratingunit.getChangeId());
            ratingunit.setLevelPath(levelPath + "/" + maxLevelCode);
        }
        mapper.insert(ratingunit);

        // 记录变更
        rercordChanges(factory, CollUtil.newArrayList(ratingunit), equipmentdetmapper, RatingChangeEnum.ADD_OPT);

        return Response.success(ratingunit.getId());
    }

    @TaskAnnotation("insertBatch")
    public Response insertBatch(SessionFactory factory, RatingUnitChangeBatchDto dto) {
        List<UnitChangeDetBean> det = new ArrayList<>();
        dto.getDet().stream().forEach(d -> {
            det.add(Convert.convert(UnitChangeDetBean.class, d));
        });

        UnitChangeDetBeanMapper mapper = factory.getMapper(UnitChangeDetBeanMapper.class);
        UnitEquipmentDetBeanMapper equipmentdetmapper = factory.getMapper(UnitEquipmentDetBeanMapper.class);
        if (StringUtils.isEmpty(dto.getParentId())) {
            // 没有父级，说明是根节点
            det.stream().forEach(d -> {
                d.setParentId(Constants.DEVICE_TREE_ROOT_CODE);
            });
        }
        UnitChangeDetBean parent = mapper.selectByChangeIdAndId(dto.getChangeId(), dto.getParentId());

        for (UnitChangeDetBean d : det) {
            d.setChangeId(dto.getChangeId());
            d.setPrimaryId(CodeTools.getCode32());
            d.setId(CodeTools.getCode32());
//            d.setUnitType(dto.getUnitType());//单元类型
            d.setParentId(dto.getParentId());//父节点
            d.setParentName(parent.getName());
            // 父级level+1
            d.setLevel(parent.getLevel() + 1);
            d.setFullPathCode(parent.getFullPathCode() + "/" + d.getId());
            d.setFullPathName(parent.getFullPathName() + "/" + d.getName());
            d.setDeleteFlag(0);
        }

        if (dto.getUnitType().compareTo(parent.getUnitType()) == -1) {
            return Response.fail("单元类型选择错误");
        }
        // 获取该层级的最大编码
        Integer maxLevelCode = mapper.getMaxLevelCodeByLevelAndChangeId(parent.getLevel() + 1, dto.getChangeId());//该批次都同个父级下的层级
        maxLevelCode = maxLevelCode == null ? 1 : maxLevelCode + 1;
        for (UnitChangeDetBean d : det) {
            d.setLevelCode(maxLevelCode);
            d.setSort(maxLevelCode);
            d.setLevelPath(parent.getLevelPath() + "/" + maxLevelCode);
            maxLevelCode = maxLevelCode + 1;
        }
        mapper.batchInsert(det);

        rercordChanges(factory, det, equipmentdetmapper, RatingChangeEnum.ADD_OPT);//新增记录累计到变更表

        return Response.success(det.get(0).getId());
    }

    /**
     * 根据变更单id、类型 查重复数据
     *
     * @param factory
     * @param changeId     变更单id
     * @param unitTypelist 类型s
     * @param det          新增数据
     * @param id           更新Id
     */
    @TaskAnnotation("checkRepeat")
    public void checkRepeat(SessionFactory factory, String changeId, List<String> unitTypelist, List<UnitCheckPo> det, String id, Date updateTime) {
        if(StrUtil.isBlank(changeId)){
            return;
        }

        UnitChangeBeanMapper mapper = factory.getMapper(UnitChangeBeanMapper.class);
        UnitChangeBean unitchangebean = factory.getMapper(UnitChangeBeanMapper.class).selectByPrimaryKey(changeId);//获取变更单最后更新时间
        if (unitchangebean.getUpdateTime() == null || updateTime == null) {
            return;
        }
        //是否小于数据库最后更新时间
        long between = DateUtil.between(unitchangebean.getUpdateTime(), updateTime,  DateUnit.MS, false);
        if (between < 0) {
            Assert.isFalse(true, "信息已过期请刷新界面");
        }else{
            mapper.updateUpdateTimeAndUpdateByAndUpdateByNameById(new Date(), getEamUser().getAccount(), getEamUser().getName(), changeId);
        }

        //删除没有查重参数
        if (CollUtil.isEmpty(unitTypelist)) {
            return;
        }

        ArrayList<String> sbjlist = CollUtil.newArrayList(LEVEL4.getValue(), LEVEL5.getValue(), LEVEL6.getValue());
        //新增类型是否 是单元、设备、部件
        if (det.stream().anyMatch(d->sbjlist.contains(d.getUnitType()))) {
            unitTypelist = sbjlist;
        }

        // 相应变更id 根据层级 获取 已存在 的 （部门)、（单位）、（单元、设备、部件）
        List<String> eqIdlisted = factory.getMapper(UnitChangeDetBeanMapper.class).queryEquipmentIdByChangeIdAndUnitTypeIn(changeId, unitTypelist, id);
        Iterator<UnitCheckPo> iterator = det.iterator();
        while (iterator.hasNext()) {
            UnitCheckPo dto = iterator.next();
            if (eqIdlisted.contains(dto.getId())) {
                Assert.isFalse(true, StrUtil.format("{} 存在重复"), dto.getName());
            }
        }
    }


    /**
     * 记录变更记录
     *
     * @param det
     * @param equipmentdetmapper
     */
    private void rercordChanges(SessionFactory factory, List<UnitChangeDetBean> det, UnitEquipmentDetBeanMapper equipmentdetmapper, RatingChangeEnum opt) {
        List<UnitChangeDetBean> changdetlist = factory.getMapper(UnitChangeDetBeanMapper.class).queryByChangeId(det.get(0).getChangeId());
        det.stream().forEach(d -> {
            //先删除原来的
            if (opt.getValue().equals(RatingChangeEnum.UP_OPT.getValue())) {
                equipmentdetmapper.deleteByChangePrimaryId(d.getPrimaryId());
            }
            List<String> fullpathcode = StrUtil.split(d.getFullPathCode(), "/");
            List<String> fullpathname = StrUtil.split(d.getFullPathName(), "/");
            if (CollUtil.isNotEmpty(fullpathcode)) {
                if (fullpathcode.size() >= 3) {
                    // 找出单位 的 单元id
                    String deptEqId = fullpathcode.get(2);
                    // 根据单元id 的 单位id
                    UnitChangeDetBean unitChangeDetBean = changdetlist.stream().filter(ch -> ch.getId().equals(deptEqId)).findFirst().get();
                    d.setDeptId(unitChangeDetBean.getEquipmentId());// 单位id赋值
                    // 单元名称赋值
                    d.setDeptName(fullpathname.get(2));
                }
            }
        });
        // 转换一下
        List<UnitEquipmentDetBean> eqdetlist = det.stream().map(d -> {
            UnitEquipmentDetBean bean = Convert.convert(UnitEquipmentDetBean.class, d);
            bean.setId(CodeTools.getCode32());
            bean.setDeptId(d.getDeptId());
            bean.setDeptName(d.getDeptName());
            bean.setChangePrimaryId(d.getPrimaryId());//比对id
            bean.setOptType(opt.getValue());
            return bean;
        }).collect(Collectors.toList());
        equipmentdetmapper.batchInsert(eqdetlist);
    }


    @TaskAnnotation("update")
    public Response update(SessionFactory factory, UnitChangeDetBean ratingunit) {

        UnitChangeBeanMapper ordermapper = factory.getMapper(UnitChangeBeanMapper.class);
        ordermapper.updateUpdateTimeAndUpdateByAndUpdateByNameById(new Date(), getEamUser().getAccount(), getEamUser().getName(), ratingunit.getChangeId());//更新变更单最后更新时间
        UnitChangeDetBeanMapper mapper = factory.getMapper(UnitChangeDetBeanMapper.class);
        UnitEquipmentDetBeanMapper equipmentdetmapper = factory.getMapper(UnitEquipmentDetBeanMapper.class);
        // 数据库未更新时的设备信息
        UnitChangeDetBean origin = mapper.selectByChangeIdAndId(ratingunit.getChangeId(), ratingunit.getId());
        if (!StringUtils.equals(ratingunit.getParentId(), "0")) {
            UnitChangeDetBean parent = mapper.selectByChangeIdAndId(ratingunit.getChangeId(), ratingunit.getParentId());
            if (ratingunit.getUnitType().compareTo(parent.getUnitType()) == -1) {
                return Response.fail("单元类型选择错误");
            }
        }
        // 更新当前节点的所有子节点的parent_name
        mapper.updateParentNameByIdAndChangeId(ratingunit.getId(), ratingunit.getName(), ratingunit.getChangeId());
        if (!StringUtils.equals(origin.getName(), ratingunit.getName())) {
            // 如果名字更新，则更新full_path_name
            mapper.updateFullPathName(origin.getName(), ratingunit.getName(), ratingunit.getId(), ratingunit.getChangeId());
        }
        mapper.updateByPrimaryKeySelective(ratingunit);
        ratingunit = mapper.selectByChangeIdAndId(ratingunit.getChangeId(), ratingunit.getId());//重新查出来

        // 记录变更
        rercordChanges(factory, CollUtil.newArrayList(ratingunit), equipmentdetmapper, RatingChangeEnum.UP_OPT);

        return Response.success();
    }

    @TaskAnnotation("delete")
    public Response delete(SessionFactory factory, String id, String changeId) {
        UnitChangeDetBeanMapper mapper = factory.getMapper(UnitChangeDetBeanMapper.class);
        UnitEquipmentDetBeanMapper equipmentdetmapper = factory.getMapper(UnitEquipmentDetBeanMapper.class);
        UnitOldBeanMapper oldBeanMapper = factory.getMapper(UnitOldBeanMapper.class);
        if (mapper.countChildren(id, changeId) > 0) {
            return Response.fail("该节点下还有子节点，不能删除");
        }
        UnitChangeDetBean ratingunit = mapper.selectByChangeIdAndId(changeId, id);
        mapper.deleteByChangeIdAndId(changeId, id);
        UnitOldBean unitOldBean = oldBeanMapper.selectByPrimaryKey(ratingunit.getPrimaryId());
        //如果删除的节点在 备份树 里不为空 ，则记录（如果在备份树中找不到，代表删除的数据为新增数据）
        if (ObjectUtil.isNotNull(unitOldBean)) {
            // 记录变更
            rercordChanges(factory, CollUtil.newArrayList(ratingunit), equipmentdetmapper, RatingChangeEnum.DEL_OPT);
            return Response.success();
        }
        return Response.success();
    }

    @TaskAnnotation("getById")
    public Response<UnitChangeDetBean> getById(SessionFactory factory, String id, String changeId) {
        UnitChangeDetBeanMapper mapper = factory.getMapper(UnitChangeDetBeanMapper.class);
        UnitChangeDetBean ratingunit = mapper.selectByChangeIdAndId(changeId, id);
        Assert.notNull(ratingunit, "单元不存在");
        ratingunit.setDeptName(orgCacheUtils.getOrgNameById(ratingunit.getDeptId()));
        return Response.success(ratingunit);
    }

    @TaskAnnotation("getTreeLazy")
    public Response getTreeLazy(SessionFactory factory, String parentId, String changeId) {
        UnitChangeDetBeanMapper mapper = factory.getMapper(UnitChangeDetBeanMapper.class);
        if (StringUtils.isEmpty(parentId)) {
            parentId = "02000000000001";
        }

        List<UnitChangeDetBean> list = mapper.list(parentId, null, changeId);
        // 获取权限
        ArrayList<String> units = CollUtil.newArrayList(getEamUser().getDeptId());
        List<AppOrgJurisdictionBean> appOrgJurisdictionBeans = Optional.ofNullable(getEamUser())
                .map(EamUser::getUserOwnJurisdictionBean)
                .map(UserOwnJurisdictionBean::getAppOrgJurisdictionBeanList).orElse(new ArrayList<>());
        Optional<AppOrgJurisdictionBean> firstopt = appOrgJurisdictionBeans.stream().filter(j -> getEamUser().getAppId().equals(j.getAppId())).findFirst();
        if (firstopt.isPresent()) {
            units.addAll(firstopt.get().getOrgStrList());
        }
        //（可以查看同个部门不同单位设备）
        list = list.stream().filter(l -> units.contains(l.getDeptId())).collect(Collectors.toList()); // 可以看权限配置的范围
//        list = list.stream().filter(l -> l.getDeptId().equals(getEamUser().getDeptId())).collect(Collectors.toList()); // 只可以看自己部门的
        if (CollUtil.isNotEmpty(list)) {
            list.stream().forEach(equipment -> equipment.setChildrenNum(mapper.countChildren(equipment.getId(), changeId)));
            return Response.succ(list);
        } else {
            return Response.succ(new ArrayList());
        }
    }

    @TaskAnnotation("getFloor")
    public Response<List> getFloor(SessionFactory factory, String parentId, String id, String changeId) {
        UnitChangeDetBeanMapper mapper = factory.getMapper(UnitChangeDetBeanMapper.class);
        List<Select> selects = getSelects();
        // 当前id和父id都为空，说明是新增根节点，返回全部
        if (StringUtils.isAllEmpty(parentId, id)) {
            return Response.success(selects);
        }
        // 父级设备
        UnitChangeDetBean ratingunit = mapper.selectByChangeIdAndId(changeId, parentId);
        // 当前id为空，父id不为空，说明是新增子节点
        if (StringUtils.isEmpty(id)) {
            selects.stream().forEach(select -> select.setDisabled(ratingunit.getUnitType().compareTo(select.getValue()) > 0));
            return Response.succ(selects);
        }
        List<UnitChangeDetBean> children = mapper.list(id, null, changeId);
        String s = children.size() > 0 ? children.stream().map(UnitChangeDetBean::getUnitType).min((x, y) -> x.compareTo(y)).get() : "0";
        selects.stream().forEach(select -> select.setDisabled((ratingunit != null && ratingunit.getUnitType().compareTo(select.getValue()) > 0) || (!"0".equals(s) && s.compareTo(select.getValue()) < 0)));
        return Response.succ(selects);
    }

    @TaskAnnotation("searchByName")
    public Response<List<UnitChangeDetBean>> searchByName(SessionFactory factory, String name, String deptId, String changeId) {
        if (StringUtils.isEmpty(name)) {
            return Response.succ(Collections.emptyList());
        }
        UnitChangeDetBeanMapper mapper = factory.getMapper(UnitChangeDetBeanMapper.class);
        List<UnitChangeDetBean> result = mapper.listBydeptId(deptId, name, changeId);
        return Response.succ(result);
    }

    /**
     * 获取所有层级下拉
     *
     * @return
     */
    private static List<Select> getSelects() {
        List<Select> list = Lists.newArrayList();
        for (UnitTypeEnum item : UnitTypeEnum.values()) {
            Select select = new Select();
            select.setLabel(item.getLabel());
            select.setValue(item.getValue());
            select.setDisabled(false);
            list.add(select);
        }
        return list;
    }

    @TaskAnnotation("getParentIds")
    public Response<List<String>> getParentIds(SessionFactory factory, String id, String changeId) {
        List<String> list = new LinkedList<>();
        UnitChangeDetBean equipment = getById(factory, id, changeId).getData();
        while (!StringUtils.equals(equipment.getParentId(), "0")) {
            equipment = getById(factory, equipment.getParentId(), changeId).getData();
            list.add(0, equipment.getId());
        }
        return Response.succ(list);
    }

    /**
     * 获取同组织下，最左上的设备台账
     *
     * @param factory
     * @param deptId
     * @return
     */
    @TaskAnnotation("getLeftUpperRatingUnitByDeptId")
    public Response getLeftUpperRatingUnitByDeptId(SessionFactory factory, String deptId, String changeId) {
        UnitChangeDetBean equipment = null;
        UnitChangeDetBeanMapper mapper = factory.getMapper(UnitChangeDetBeanMapper.class);
        if (StringUtils.isBlank(deptId)) {
            deptId = ThreadLocalContext.get().getDeptId();
            OrgBean orgBean = CommonUtils.ok(systemFeignService.querySingleOrg(deptId));
            Assert.notNull(orgBean, "用户所在组织不存在");
            equipment = mapper.getLeftUpperRatingByDeptId(orgBean.getId(), changeId);
            if (equipment != null) {
                return Response.ok(equipment);
            }
        } else {
            UnitChangeDetBean unit = mapper.getLeftUpperRatingByDeptId(deptId, changeId);
            if (ObjectUtil.isNull(unit)) {
                unit = mapper.getLeftUpperEquipmentByDeptId(deptId, changeId);
            }
            return Response.ok(unit);
        }
        return Response.ok(equipment);
    }


    @TaskAnnotation("changeSort")
    public Response<String> changeSort(SessionFactory factory, RatingUnitSortDto dto) {

        UnitChangeDetBeanMapper mapper = factory.getMapper(UnitChangeDetBeanMapper.class);
        //上移
        if (dto.getSortType().equals(UnitSortTypeEnum.UP.getLabel())) {
            List<UnitChangeDetBean> minlist = mapper.queryByParentIdAndSortBefore(dto.getParentId(), dto.getSort(), dto.getChangeId());
            if (CollUtil.isNotEmpty(minlist)) {
                UnitChangeDetBean bean = minlist.get(minlist.size() - 1);//它的上一位
                //交换序号
                mapper.updateSortById(bean.getSort(), dto.getId(), dto.getChangeId());//把上一位的序号哥给它
                mapper.updateSortById(dto.getSort(), bean.getId(), dto.getChangeId());//把自己的序号给上一位
            }
        }
        if (dto.getSortType().equals(UnitSortTypeEnum.DOWN.getLabel())) {
            List<UnitChangeDetBean> maxlist = mapper.queryByParentIdAndSortAfter(dto.getParentId(), dto.getSort(), dto.getChangeId());
            if (CollUtil.isNotEmpty(maxlist)) {
                UnitChangeDetBean bean = maxlist.get(0);//它的下一位
                //交换序号
                mapper.updateSortById(bean.getSort(), dto.getId(), dto.getChangeId());//把下一位的序号给自己
                mapper.updateSortById(dto.getSort(), bean.getId(), dto.getChangeId());//把自己的序号给下一位
            }
        }

        return Response.succ(dto.getParentId());
    }


}
